/*
 * Copyright (C) 2014 Ningbo Yuanqun Inc., All Rights Reserved.
 */
package com.yuanqunsoft.alimigration.common;

import java.io.File;
import java.io.FileNotFoundException;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
 * <p>
 * Helper class for the project.
 * </p>
 * 
 * @author ykt
 * @author ShaoYu
 * @version 1.0
 */
public final class Helper {
    private static final Logger logger = LogManager.getLogger(Helper.class);

    private Helper() {

    }

    public static void checkNull(Object obj, String name) {
        if (obj == null) {
            String errMsg = "The parameter '" + name + "' should not be null.";
            IllegalArgumentException ex = new IllegalArgumentException(errMsg);
            logger.error(errMsg, ex);
            throw ex;
        }
    }

    /**
     * <p>
     * 检测字符串是否为空或为null
     * </p>
     * 
     * @param str
     *            待检测的字符串
     * @param name
     *            待检测字符串对应的参数名称
     */
    public static void checkStringNullorEmpty(String str, String name) {
        checkNull(str, name);

        if (str.trim().length() == 0) {
            String errMsg = "The String '" + name + "' should not be empty.";
            IllegalArgumentException ex = new IllegalArgumentException(errMsg);
            logger.error(errMsg, ex);
            throw ex;
        }
    }

    /**
     * <p>
     * Check if the given file exists.
     * </p>
     * 
     * @param targetFile
     *            the file to be tested
     * @throws FileNotFoundException
     *             if the file is not found
     */
    public static void checkFileExist(File targetFile) throws FileNotFoundException {
        if (targetFile == null || !targetFile.exists()) {
            String errMsg;
            if (targetFile == null) {
                errMsg = "Parameter \"null\" can not be resolved to a file.";
            } else {
                errMsg = "Target file is not exist: " + targetFile.getAbsolutePath();
            }
            FileNotFoundException ex = new FileNotFoundException(errMsg);
            logger.error(errMsg, ex);
            throw ex;
        }
    }

    /**
     * <p>
     * 获得文件 <code>file</code> 相对于路径 <code>root</code> （包含）的相对路径。
     * </p>
     * <p>
     * 如：<code>root</code> 为 <b>"Project"</b>，<code>file</code> 为 <b>"D:/Example/Project/file.java"</b>，
     * 那么返回的相对路径为<b>"Project/file.java"</b>。
     * </p>
     * <p>
     * 如果 <code>root</code> 不是 <code>file</code> 中的某一级路径，则返回null。
     * </p>
     * 
     * @param root
     *            相对的根目录
     * @param file
     *            需要获得相对路径的文件
     * @return 相对路径，如果 <code>root</code> 不是 <code>file</code> 中的某一级路径，则返回null。
     */
    public static String getRelativePath(String root, File file) {
        checkStringNullorEmpty(root, "root");

        String absPath = file.getAbsolutePath();
        int rootIndex = 0;
        while ((rootIndex = absPath.indexOf(root, rootIndex)) != -1) {
            if ((absPath.charAt(rootIndex - 1) == File.separatorChar)
                    && (absPath.charAt(rootIndex + root.length()) == File.separatorChar)) {
                break;
            } else {
                rootIndex += 4;
            }
        }
        return rootIndex != -1 ? absPath.substring(rootIndex) : null;
    }

    /**
     * <p>
     * 验证后缀名是否符合规范，后缀名的期望匹配列表在配置文件中给出，默认以符号 <code>|</code> 分割。 传入的 <code>propertiesName</code> 参数应该由
     * {@link GlobalConfig}给出。
     * </p>
     * <p>
     * 例如，一个正确的例子是：
     * 
     * <pre>
     * validExt({@link GlobalConfig#ENGINE_PROPERTIES_SUPPORT_SINGLE_FILE_TYPE}, "example.class")
     * </pre>
     * 
     * 在这个例子中，{@link #validExt(String, String)}方法将验证<code>example.class</code> 的后缀名是否是
     * {@link GlobalConfig#ENGINE_PROPERTIES_SUPPORT_SINGLE_FILE_TYPE}所 指向的配置文件内容
     * <b>.java|.class|.properties|.xml</b> 中的一个，如果是则返回true，否则返回false
     * </p>
     * 
     * @param propertiesName
     *            期待校验的后缀名列表对应的配置名称
     * @param name
     *            待验证的文件名
     * @return true-通过验证，false-不通过验证
     */
    public static boolean validExt(String propertiesName, String name) {
        return validExt(propertiesName, name, "\\|");
    }

    /**
     * <p>
     * 验证后缀名是否符合规范，后缀名的期望匹配列表在配置文件中给出，默认以符号 <code>|</code> 分割。 传入的 <code>propertiesName</code> 参数应该由
     * {@link GlobalConfig}给出。
     * </p>
     * <p>
     * 例如，一个正确的例子是：
     * 
     * <pre>
     * validExt({@link GlobalConfig#ENGINE_PROPERTIES_SUPPORT_SINGLE_FILE_TYPE}, 
     *          "example.class",
     *          ",")
     * </pre>
     * 
     * 在这个例子中，{@link #validExt(String, String, String)}方法将验证<code>example.class</code> 的后缀名是否是
     * {@link GlobalConfig#ENGINE_PROPERTIES_SUPPORT_SINGLE_FILE_TYPE}所 指向的配置文件内容
     * <b>.java,.class,.properties,.xml</b> 中的一个，如果是则返回true，否则返回false
     * </p>
     * 
     * @param propertiesName
     *            期待校验的后缀名列表对应的配置名称
     * @param name
     *            待验证的文件名
     * @param separator
     *            后缀名列表的分隔符
     * @return true-通过验证，false-不通过验证
     */
    public static boolean validExt(String propertiesName, String name, String separator) {

        checkStringNullorEmpty(propertiesName, "propertiesName");
        checkStringNullorEmpty(name, "name");
        checkStringNullorEmpty(separator, "separator");

        String[] exts = PropertiesUtil.getProperty(propertiesName).split(separator);
        for (String ext : exts) {
            if (name.endsWith(ext)) {
                return true;
            }
        }
        return false;
    }
}
